avatar

0xarch

重度抑郁爱好者

目录

站点信息

总字数

18409

分类数

7

标签数

10

总文章

37

运行时长

000 天

构建信息

构建时间

Sun Jul 19 2026

Fewu

3.7.86

Nuwari / NEXTario

1.0

本代码是作者初学时编写的,现已在 Next、Nuwari 等地使用了更新且略微规范的代码,不建议再使用本文章提及的代码。

JavaScript

参数

markdown_content: 文章容器(Node)

需要更改的地方

#toc: 挂载目录的容器

Code

function TOC(markdown_content) {
    let toc = document.querySelector("#toc");
    if(!toc) return;
    let tocList = markdown_content.querySelectorAll("h1, h2, h3, h4, h5, h6");
    let liList = [];
    tocList.forEach((v) => {
        let pid = '_' + Date.now().toString(36) + Math.random().toString(36).replace(/[\s\S]{3}/, '');
        v.id = pid;
        const H = v.nodeName[1];
        let li = document.createElement('li');
        li.classList.add(`li-${H}`);
        li.setAttribute('pid', pid);
        li.textContent = v.textContent;
        li.addEventListener("click", () => {
            window.scrollBy({ top: v.getBoundingClientRect().y, behavior: "smooth" });
        });
        toc.appendChild(li);
        liList.push(li);
    })
    let tocArr = Array.from(tocList);
    const removeClass = () => {
        liList.forEach(v => v.classList.remove("active"));
    }
    const update = () => {
        for (let i = 0; i < tocArr.length; i++) {
            let v = tocArr[i];
            let rect = v.getBoundingClientRect();
            let top = rect.top + rect.height;
            if (top > 0) {
                removeClass();
                let li = liList[i];
                li.classList.add('active');
                /*
                这两句代码用来实现目录左侧的进度条,需要搭配CSS实现,删除没有影响。
                CSS见下文
                toc.style.setProperty('--g-start',li.offsetTop+li.getBoundingClientRect().height-5+'px');
                toc.style.setProperty('--g-end',li.offsetTop+li.getBoundingClientRect().height+5+'px');
                */
                break;
            }
        }
    }
    let ticking = false;
    window.addEventListener("scroll", () => {
        if (!ticking) {
            window.requestAnimationFrame(() => {
                update();
                ticking = false;
            })
        }
        ticking = true;
    });
    update();
}

CSS

需要更改的地方

--brand-color: 高亮颜色 --radius: 圆角

Code

#toc{
    margin: 0;
    list-style: none;
    padding: 0.75rem;
    border-radius: 0.75rem;
    border: 1px solid transparent;
}
#toc::before{
    position: absolute;
    top: 0;
    left: 0;
    width: .1rem;
    height: 100%;
    content: '';
    background: linear-gradient(var(--brand-color) var(--g-start),transparent var(--g-end));
}
#toc>li{
    cursor: pointer;
    padding: 0.125rem 0.25rem;
    border-radius: var(--radius);
    transition: color .2s ease-in-out,background .2s ease-in-out;
}
#toc>.li-1{
    font-size: larger;
}
#toc>.li-2{
    font-size: large;
    padding-left: 0.65rem;
}
#toc>.li-3{
    padding-left: 1.25rem;
}
#toc>li:hover{
    background: var(--brand-color-75);
    color: #fff;
}
#toc>li.active{
    color: var(--brand-color);
}
#toc>li.active:hover{
    background-color: var(--brand-color-25);
}
WebJS - 滚动目录实现
作者0xarch
发布于2024-03-04
许可协议CC BY-NC-SA 4.0